#include "instantiator.h"

#include "baseelement.h"
#include "realelement.h"
#include "inelement.h"
#include "clock.h"

template class ClassFactory<BaseElement>;
template class ClassFactory<RealElement>;
template class ClassFactory<InElement>;
template class ClassFactory<ClockElement>;

Instantiator Instantiator::instance;

Instantiator::Instantiator()
{
    this->registerClass<BaseElement>();
    this->registerClass<RealElement>();
    this->registerClass<InElement>();
    this->registerClass<ClockElement>();
}

Instantiator::Instantiator(const Instantiator& instantiator) { }

Instantiator::~Instantiator()
{
    qDeleteAll( mMap.values() );
}

//Регистрация типа для [Custom Element]
template<typename T> void Instantiator::registerClass()
{
    QString className = T::staticMetaObject.className();
    mMap[className] = new ClassFactory<T>;
}

//Создать объект по имени типа
QObject* Instantiator::create(const QString& className)
{
    if ( mMap.contains( className ) )
       return mMap[className]->create();

    return 0;
}

BaseElement* Instantiator::createElement(const QString& className)
{
    QObject* element = this->create(className);
    if (element != 0)
        return qobject_cast<BaseElement*>(element);
    return 0;
}

BaseElement* Instantiator::buildElement(const QString& alias)
{
    ObjectConfig config = ObjectsLoader::getInstance().getConfig(alias);
    QObject* element = this->create(config.className);
    if (element != 0)
    {
        ConfiguredElement* configured = dynamic_cast<ConfiguredElement*>(element);
        if (configured != NULL)
        {
            configured->init(config.fileName);
        }
        return qobject_cast<BaseElement*>(element);
    }
    return 0;
}

Instantiator& Instantiator::getInstance()
{
    return Instantiator::instance;
}

// Типы
template void Instantiator::registerClass<BaseElement>();
template void Instantiator::registerClass<RealElement>();
template void Instantiator::registerClass<InElement>();
template void Instantiator::registerClass<ClockElement>();
